﻿using System;
using System.Windows;
using System.Windows.Controls;
using XEvolve.Presentation.Extensions;

namespace XEvolve.Presentation.Controls.ListViewAdvisors
{
    public class DragToScroll : IDependencyObjectAdvisor
    {
        private DateTime? mouseOverStartTime;
        private static readonly TimeSpan MIN_HOVER_TIME = new TimeSpan(500 * 10000);

        private ListView target;

        public void Initialize(DependencyObject element)
        {
            target = (ListView)element;
            target.AddHandler(UIElement.DragOverEvent, new DragEventHandler((sender, args) => OnDragOver(args)));
        }

        protected virtual void OnDragOver(DragEventArgs e)
        {
            var now = DateTime.Now;
            var scrollContent = target.FindChild<ScrollViewer>();
            var header = target.FindChild<GridViewHeaderRowPresenter>();

            var position = e.GetPosition(scrollContent);
            var isNearTop = position.Y > header.ActualHeight && position.Y < header.ActualHeight + 20;
            var isNearBottom = position.Y > scrollContent.ActualHeight - 20 && position.Y < scrollContent.ActualHeight;
            if (isNearTop || isNearBottom)
            {
                if (!mouseOverStartTime.HasValue)
                {
                    mouseOverStartTime = now;
                }
                else if ((now - mouseOverStartTime.Value) > MIN_HOVER_TIME && e.OriginalSource != null)
                {
                    ScrollIfNeeded(((FrameworkElement)e.OriginalSource).DataContext, isNearTop);
                }
            }
            else
            {
                mouseOverStartTime = null;
            }
        }

        private void ScrollIfNeeded(object item, bool shouldScrollUp)
        {
            var index = target.Items.IndexOf(item);
            if (index <= 0 || index >= target.Items.Count - 1) return;
            var listViewItem = (ListViewItem)target.ItemContainerGenerator.ContainerFromIndex(shouldScrollUp ? index - 1 : index + 1);
            listViewItem.BringIntoView();
        }
    }
}